package com.bpc.cs.service;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.bpc.cs.constant.Constant;
import com.bpc.cs.dao.IFactorChoiceDAO;
import com.bpc.cs.dao.IFactorDAO;
import com.bpc.cs.dao.IRuleDAO;
import com.bpc.cs.dao.ISchemeDAO;
import com.bpc.cs.dto.RuleDTO;
import com.bpc.cs.managed.dvo.FactorDVO;
import com.bpc.cs.managed.dvo.RuleDVO;
import com.bpc.cs.managed.dvo.SchemeDVO;
import com.bpc.cs.util.Message;
import com.bpc.cs.util.Util;

/**
 * @author   phan_tp
 * @datetime Nov 30, 2012 : 4:45:57 PM
 */

@Transactional(readOnly = false)
public class RuleService implements IRuleService {

	IRuleDAO ruleDAO;
	IFactorDAO factorDAO;
	ISchemeDAO schemeDAO;
	IFactorChoiceDAO factorChoiceDAO;

	/**
	 * Get list Rule schemeID
	 * @param int schemeID
	 * @return RuleDTO
	 */
	@Override
	public List<RuleDVO> getRuleBySchemeID(int schemeID) {
		return Util.cvnRuleDTO2DVO(schemeDAO.selectRuleBySchemeByID(schemeID));
	}

	/**
	 * Add new rule for scheme
	 * @param int schemeID
	 * @param int factorID
	 * @param float weight
	 * @return Message
	 */
	@Override
	public Message addRule(SchemeDVO schemeDVO, FactorDVO factorDVO, float weight) {
		// Message object is used to transfer to bean
		Message msg = new Message();

		// Check factor is existed in set of rule or not
		if (ruleDAO.isDuplicatedFactorName(schemeDVO.getSchemeID(), factorDVO.getFactorID())) {
			// Factor Name is duplicated
			msg.setResultBoolean(false);
			msg.setMessageKey(Constant.DUPLICATE_FACTOR);
			return msg;
		} else {
			// Factor Name isn't duplicated
			// Call DAO method to execute add new rule
			ruleDAO.insertRule(new RuleDTO(Util.cvnSchemeDVO2DTO(schemeDVO), Util.cvnFactorDVO2DTO(factorDVO), weight));
			msg.setResultBoolean(true);
		}
		return msg;
	}

	/**
	 * Edit rule for scheme
	 * @param int ruleID
	 * @param FactorDVO factorDVO
	 * @param float weight
	 * @param List<RuleDVO> listRuleDVO
	 * @return Message
	 */
	public Message editRule(RuleDVO ruleDVO, SchemeDVO schemeDVO, FactorDVO factorDVO,
							float weight, List<RuleDVO> listRuleDVO) {
		// Message object is used to transfer to bean
		Message msg = new Message();

		// Flag vaiable to check update factor or not
		boolean isUpdateFactor = false;

		// Check rule is updated factor or not
		for (RuleDVO ruleTmp : listRuleDVO) {
			if (ruleTmp.getRuleID() == ruleDVO.getRuleID() && ruleTmp.getFactorID() != factorDVO.getFactorID()) {
				isUpdateFactor = true;
				break;
			}
		}

		if (isUpdateFactor) {
			// Check duplicated of Factor if user update factor too
			if (ruleDAO.isDuplicatedFactorName(schemeDVO.getSchemeID(), factorDVO.getFactorID())) {
				// FactorName is duplicated
				msg.setResultBoolean(false);
				msg.setMessageKey(Constant.DUPLICATE_FACTOR);
				return msg;
			}
		}

		// Create ruleDTO object
		RuleDTO ruleDTO = Util.cvnRuleDVO2DTO(ruleDVO);
		ruleDTO.setFactorDTO(Util.cvnFactorDVO2DTO(factorDVO));
		ruleDTO.setSchemeDTO(Util.cvnSchemeDVO2DTO(schemeDVO));
		ruleDTO.setWeight(weight);

		// Call DAO to execute update rule information
		ruleDAO.updateRule(ruleDTO);

		// Set result return is true
		msg.setResultBoolean(true);

		return msg;
	}

	/**
	 * Remove rule
	 * @param int ruleID
	 * @return boolean TRUE : remove successfully
	 * 				   FALSE: remove failed
	 */
	public boolean removeRule(int ruleID) {
		// Check Data in factorchoice object before execute remove action
		return factorChoiceDAO.countRuleID(ruleID) > 0 ? false : ruleDAO.deleteRule(ruleID);
	}

	/**
	 * Remove entire rule and factor choice
	 * @param int ruleID
	 * @return boolean TRUE : Delete successfully
	 * 				   FALSE: Delete failed
	 */
	public boolean removeEntireRule(int ruleID) {
		return ruleDAO.deleteEntireRule(ruleID);
	}

	/**
	 * Get ScoringSchemeDAO
	 * @return IScoringSchemeDAO
	 */
	public IRuleDAO getRuleDAO() {
		return ruleDAO;
	}

	/**
	 * Set ScoringSchemeDAO
	 * @param ruleDAO IScoringSchemeDAO to set
	 */
	public void setRuleDAO(IRuleDAO ruleDAO) {
		this.ruleDAO = ruleDAO;
	}

	/**
	 * @return the factorDAO
	 */
	public IFactorDAO getFactorDAO() {
		return factorDAO;
	}

	/**
	 * @param factorDAO the factorDAO to set
	 */
	public void setFactorDAO(IFactorDAO factorDAO) {
		this.factorDAO = factorDAO;
	}

	/**
	 * @return the factorChoiceDAO
	 */
	public IFactorChoiceDAO getFactorChoiceDAO() {
		return factorChoiceDAO;
	}

	/**
	 * @param factorChoiceDAO the factorChoiceDAO to set
	 */
	public void setFactorChoiceDAO(IFactorChoiceDAO factorChoiceDAO) {
		this.factorChoiceDAO = factorChoiceDAO;
	}

	/**
	 * @return the schemeDAO
	 */
	public ISchemeDAO getSchemeDAO() {
		return schemeDAO;
	}

	/**
	 * @param schemeDAO the schemeDAO to set
	 */
	public void setSchemeDAO(ISchemeDAO schemeDAO) {
		this.schemeDAO = schemeDAO;
	}

}
